package com.tinyshardingjdbc.tinyshardingjdbc.shardingasync;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.ParameterUtils;
import com.tinyshardingjdbc.tinyshardingjdbc.shardingasync.annotaion.TinyShardingJdbc;
import com.tinyshardingjdbc.tinyshardingjdbc.shardingasync.annotaion.TinyShardingJdbcDTO;
import com.tinyshardingjdbc.tinyshardingjdbc.shardingasync.annotaion.TinyShardingJdbcVo;
import org.apache.ibatis.cache.CacheKey;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.plugin.*;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;

import java.util.Properties;

;


/**
 * 需要在分页前面
 */
@Intercepts({
        @Signature(type = org.apache.ibatis.executor.Executor.class, method = "update", args = {MappedStatement.class, Object.class}),
        @Signature(type = org.apache.ibatis.executor.Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class}),
        @Signature(type = org.apache.ibatis.executor.Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class, CacheKey.class, BoundSql.class})

})
public class AreaInterceptors implements Interceptor {


    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        try {
            MappedStatement mappedStatement = (MappedStatement) invocation.getArgs()[0];
            String id = mappedStatement.getId();
            Class<?> classType = Class.forName(id.substring(0, mappedStatement.getId().lastIndexOf(".")));
            TinyShardingJdbc tinyShardingJdbc = classType.getAnnotation(TinyShardingJdbc.class);
            if (tinyShardingJdbc != null) {
                Object[] args = invocation.getArgs();
                Object parameter = args[1];
                TinyShardingJdbcDTO tinyShardingJdbcDTO = isPage(parameter);
                TinyShardingJdbcVo tinyShardingJdbcVo = new TinyShardingJdbcVo(tinyShardingJdbc,
                        null,
                        classType, tinyShardingJdbcDTO.isNeedPage(), tinyShardingJdbcDTO.getPage());
                return tinyShardingJdbcVo.getSqlProcessor().sqlProcessor(tinyShardingJdbcVo, invocation);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return invocation.proceed();
    }

    @Override
    public Object plugin(Object target) {
        return Plugin.wrap(target, this);
    }


    @Override
    public void setProperties(Properties properties) {

    }

    public TinyShardingJdbcDTO isPage(Object parameter) {
        TinyShardingJdbcDTO tinyShardingJdbcDTO = new TinyShardingJdbcDTO();
        tinyShardingJdbcDTO.setNeedPage(false);
        IPage<?> page = ParameterUtils.findPage(parameter).orElse(null);
        if (page != null) {
            tinyShardingJdbcDTO.setNeedPage(true);
            tinyShardingJdbcDTO.setPage(page);
        }
        return tinyShardingJdbcDTO;

    }


}
